﻿using System;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using Medianamik.Core;
using Medianamik.Core.Interfaces;
using Medianamik.Core.Security;
using Medianamik.Core.Sugar;
using Medianamik.UI.Controls;
using System.Globalization;

namespace Medianamik.UI
{
    public abstract class BaseModuleEditionPage<T1> : BasePage
        where T1 : class, INodeWrapper, INode, new()
    {
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            ScriptManager.RegisterClientScriptBlock(this, GetType(), "currentNodeId",
                "var nodeId = '" + CurrentNode.ID + "';", true);
        }

        protected override void OnPreInit(EventArgs e)
        {
            base.OnPreInit(e);

            if ((IsEdition && CurrentNode == null) || (!IsEdition && !TypeId.HasValue))
                Response.Redirect(ReturnURL);
            else
            {
                var nodeType = IsEdition ? CurrentNode.NodeType : NodeTypeManager.GetNodeType(TypeId.Value);

                if (nodeType.IsLanguageNeutral)
                    SetPageAsLanguageNeutral();
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            if (!IsPostBack)
            {
                if (IsEdition && !Roles.UserHasRight(CurrentNode, SecurityLevels.Update))
                    Response.Redirect("/medianamik/Unauthorized.aspx");
                else if (!IsEdition && TypeId.HasValue && TypeId.Value != Guid.Empty && !Roles
                    .UserHasRight(NodeTypeManager.GetNodeType(TypeId.Value), SecurityLevels.Create))
                    Response.Redirect("/medianamik/Unauthorized.aspx");

                MedianamikFormTemplate.EditionCulture = CurrentEditionCulture;

                RebindFields();
            }

            base.OnLoad(e);
        }

        private void SetPageAsLanguageNeutral()
        {
            CurrentEditionCulture = CultureInfo.InvariantCulture;

            if (Master is BaseMasterPage)
                ((BaseMasterPage)Master).RemoveLanguagePicker = true;
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            if(MedianamikFormTemplate != null)
                MedianamikFormTemplate.LockActivator.UltimatumReached += 
                    LockActivator_UltimatumReached;
        }

        protected override void OnCultureChanged(CultureChangedEventArgs e)
        {
            if (MedianamikFormTemplate != null)
            {
                MedianamikFormTemplate.EditionCulture = CurrentEditionCulture;
            }

            RebindFields();
        }

        protected virtual void Save(object sender, EventArgs e)
        {
            Page.Validate(BaseMedianamikControl.DefaultValidationGroupName);
            if (IsValid)
            {
                if(MedianamikFormTemplate != null)
                {
                    SaveAndApproveNode();
                }
                Response.Redirect(ReturnURL);
            }
        }

        protected virtual void SaveAndApproveNode()
        {
            NodeManager.SaveAndApproveNode(MedianamikFormTemplate.GetFormValue(CurrentNode), CurrentEditionCulture);
        }

        protected virtual void SaveAndPublish(object sender, EventArgs e)
        {
            Page.Validate(BaseMedianamikControl.DefaultValidationGroupName);
            if (IsValid)
            {
                if (MedianamikFormTemplate != null)
                {
                    SaveApproveAndPublishNode();
                }
                Response.Redirect(ReturnURL);
            }
        }

        protected virtual void SaveApproveAndPublishNode()
        {
            NodeManager.SaveApproveAndPublishNode(MedianamikFormTemplate.GetFormValue(CurrentNode).InnerNode, 
                CurrentEditionCulture);
        }

        protected virtual void SaveAndApprove()
        {
            Page.Validate(BaseMedianamikControl.DefaultValidationGroupName);
            if (IsValid)
            {
                ApproveNode();
                Response.Redirect(ReturnURL);
            }
        }

        protected virtual void ApproveNode()
        {
            NodeManager.ApproveNode(MedianamikFormTemplate.GetFormValue(CurrentNode), CurrentEditionCulture);
        }

        protected virtual void Revert(object sender, EventArgs e)
        {
            NodeManager.RevertAndApproveNode(CurrentNode, CurrentEditionCulture);
            Response.Redirect(ReturnURL);
        }

        protected virtual void LockActivator_UltimatumReached(object sender, EventArgs e)
        {
            Response.Redirect(ReturnURL);
        }

        //Stocké dans le ViewState pour ne pas être victime de changement au niveau du cookie
        public override CultureInfo CurrentEditionCulture
        {
            get
            {
                return ViewState["CurrentEditionCulture22"] as CultureInfo ?? 
                    base.CurrentEditionCulture;
            }
            set
            {
                ViewState["CurrentEditionCulture22"] = base.CurrentEditionCulture = value;
            }
        }

        protected virtual string ReturnURL
        {
            get { return Request.QueryString[DefaultParamNames.ReturnURL].UrlDecodeBase64(); }
        }

        public abstract MedianamikFormTemplate MedianamikFormTemplate
        {
            get;
        }

        public virtual UpdatePanel FieldsPanel
        {
            get
            {
                return null;
            }
        }
        
        [Obsolete("Use SaveButton instead", true)]
        public virtual string SaveButtonClientId
        {
            get
            {
                return null;
            }
        }

        public abstract LinkButton SaveButton
        { 
            get;
        }
        
        private T1 _currentNode;
        public virtual T1 CurrentNode
        {
            get
            {
                if (_currentNode == null)
                {
                    _currentNode = GetCurrentNode();
                }

                return _currentNode;
            }
            set
            {
                _currentNode = value;
                _nodeId = _currentNode.ID;
            }
        }

        protected virtual T1 GetCurrentNode()
        {
            T1 currentNode;

            if (IsEdition)
            {
                currentNode = NodeManager.GetNode<T1>(NodeId);
            }
            else if (TypeId.HasValue && TypeId.Value != Guid.Empty)
            {
                currentNode = NodeManager.NewNode<T1>(NodeId, TypeId.Value,
                    CurrentEditionCulture, ParentNodeId);
            }
            else
            {
                throw new Exception("Pages that inherits from BaseModulePage must provide at least one of these two properties : NodeId or TypeId.");
            }

            return currentNode;
        }

        private Guid? _parentNodeId;
        protected virtual Guid? ParentNodeId
        {
            get
            {
                if (!_parentNodeId.HasValue)
                {
                    if (ViewState[ParentNodeIdParamName] == null)
                    {
                        var strParentNodeId = Request.QueryString[ParentNodeIdParamName];

                        if (!String.IsNullOrEmpty(strParentNodeId)
                            && StringHelper.IsGuid(strParentNodeId, ref _parentNodeId))
                            ViewState[ParentNodeIdParamName] = _parentNodeId;
                    }
                    else
                        _parentNodeId = (Guid)ViewState[ParentNodeIdParamName];
                }

                return _parentNodeId;
            }
            set
            {
                ViewState["ParentNodeId"] = value;
                _parentNodeId = value;
                _parentNode = null;
            }
        }

        private Node _parentNode;
        protected virtual Node ParentNode
        {
            get
            {
                if (_parentNode == null && ParentNodeId.HasValue)
                {
                    _parentNode = NodeManager.GetNode(ParentNodeId.Value);

                    if (_parentNode != null)
                        _parentNode.DefaultCulture = CurrentEditionCulture;
                }

                return _parentNode;
            }
        }

        private Guid? _typeId = Guid.Empty;
        public virtual Guid? TypeId
        {
            get
            {
                if (_typeId == Guid.Empty)
                {
                    StringHelper.IsGuid(Request.QueryString[TypeIdParamName], ref _typeId);
                }

                return _typeId;
            }
        }

        private Guid? _nodeId;
        public virtual Guid NodeId
        {
            get
            {
                if (_nodeId == null)
                {
                    _nodeId = ViewState["NodeId"] as Guid?;

                    if (_nodeId == null)
                    {
                        if (IsEdition)
                        {
                            StringHelper.IsGuid(Request.QueryString[NodeIdParamName], ref _nodeId);

                            if(_nodeId == null)
                                throw new Exception("Pages that inherits from BaseModulePage must provide at least one of these two properties : NodeId or TypeId.");

                            ViewState["NodeId"] = _nodeId;
                        }
                    }

                    if (_nodeId == null)
                        ViewState["NodeId"] = _nodeId = Guid.NewGuid();
                }

                return _nodeId.Value;
            }
            set
            {
                ViewState["NodeId"] = _nodeId = value;
                _currentNode = default(T1);
                IsEdition = true;
            }
        }

        public virtual long? Revision
        {
            get
            {
                long result;
                if (long.TryParse(Request.QueryString[RevisionParamName], out result))
                    return result;

                return null;
            }
        }

        public virtual CultureInfo DuplicateCulture
        {
            get
            {
                if(IsEdition) //TODO: Seulement si le feature est actif
                {
                   var cultureName  = Request.QueryString[DuplicateCultureParamName];

                   if (!String.IsNullOrEmpty(cultureName))
                   {
                       CultureInfo culture;

                       try
                       {
                           culture = CultureInfo.CreateSpecificCulture(cultureName);
                       }
                       catch
                       {
                           return null;
                       }

                       return culture;
                   }
                }

                return null;
            }
        }

        protected virtual string NodeIdParamName
        {
            get
            {
                return DefaultParamNames.NodeID;
            }
        }

        protected virtual string DuplicateCultureParamName
        {
            get
            {
                return DefaultParamNames.Culture;
            }
        }

        protected virtual string RevisionParamName
        {
            get
            {
                return DefaultParamNames.Revision;
            }
        }

        protected virtual string TypeIdParamName
        {
            get
            {
                return DefaultParamNames.TypeID;
            }
        }

        protected virtual string ParentNodeIdParamName
        {
            get
            {
                return DefaultParamNames.ParentNodeID;
            }
        }

        private bool? _isEdition;
        public virtual bool IsEdition
        {
            get
            {
                if (_isEdition == null)
                {
                    _isEdition = ViewState["IsEdition"] as bool?;

                    if (_isEdition == null)
                        ViewState["IsEdition"] = _isEdition = Request.QueryString.AllKeys.Any(k => k.Equals(NodeIdParamName, 
                            StringComparison.OrdinalIgnoreCase));
                }

                return _isEdition.Value;
            }
            private set
            {
                ViewState["IsEdition"] = _isEdition = value;
            }
        }

        protected virtual void RebindFields()
        {
            SaveButton.Click += Save;
            SaveButton.OnClientClick = @"ShowOverlayOnPage();if(typeof(MedianamikLockManagement) != 'undefined' && MedianamikLockManagement != null){window.clearTimeout(MedianamikLockManagement.get_lockTimer())};";

            if (MedianamikFormTemplate != null)
            {
                MedianamikFormTemplate.SaveButtonClientId = SaveButton.ClientID;
                MedianamikFormTemplate.DataSource = CurrentNode.InnerNode;
                MedianamikFormTemplate.Revision = Revision.HasValue ? new DateTime(Revision.Value) : default(DateTime?);
                MedianamikFormTemplate.DuplicateCulture = DuplicateCulture;
                MedianamikFormTemplate.DataBind();
            }

            if (FieldsPanel != null)
                FieldsPanel.Update();
        }
    }
}
